﻿using CaseManagerLibrary.Auth;
using CaseManagerLibrary.Http;
using CaseManagerLibrary.Log;
using CaseManagerLibrary.Models;
using Newtonsoft.Json;
using PSDDownloadService.SystemSettings;
using PSDLib;
using PSDLib.Models;
using PSDLib.Protocols;
using PSDLib.Protocols.Burn;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PSDBurnService
{
    public class BurnServiceContext
    {
        public ILog Logger { get; set; }

        public bool RunAsService { get; set; }

        public bool Running { get; set; }

        public bool Burning { get; set; }

        public bool Closing { get; set; }

        public DeviceManager DeviceManager { get; set; }
        public MessageManager MessageManager { get; set; }
        public BurnManager BurnManager { get; set; }
        public BurnRuntime BurnRuntime { get; set; }
        public BurnServiceContext()
        {
            Running = false;
            Closing = false;
            Burning = false;

            DeviceManager = new DeviceManager(this);
            DeviceManager.OnGetRecordingDevice += DeviceManager_OnGetRecordingDevice;
            DeviceManager.OnDetectRecorder += DeviceManager_OnDetectRecorder;
            DeviceManager.OnUpdateCapacity += DeviceManager_OnUpdateCapacity;
            DeviceManager.OnBurnSuccess += DeviceManager_OnBurnSuccess;
            DeviceManager.OnBurnError += DeviceManager_OnBurnError;
            DeviceManager.OnBurnProgress += DeviceManager_OnBurnProgress;

            BurnManager = new BurnManager(this);
            MessageManager = new MessageManager(this);
            BurnRuntime = new BurnRuntime();
        }

        /// <summary>
        /// 初始化刻录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="logtype"></param>
        /// <param name="runAsService"></param>
        /// <returns></returns>
        public HResult Init(string username, string password, string logtype, bool runAsService)
        {
            RunAsService = runAsService;

            HResult result = null;

            if (AppSettings.Setting.Read())
            {
                switch (logtype)
                {
                    case "text":
                        Logger = new TextLog(AppSettings.Setting.LogPath);
                        break;
                    case "sql":
                        Logger = new SQLiteLog(AppSettings.Setting.LogPath, AppSettings.Setting.DeviceVersion, DeviceUUID.GetUUID());
                        break;
                    default:
                        Logger = new ConsoleLog();
                        break;
                }

                result = LoginService.Login(AppSettings.Setting.ApiServerAddress, username, password);

                if (result.success)
                {
                    if (!MessageManager.Init())
                    {
                        result.success = false;
                        result.message = "MessageManager Init Failed";
                        return result;
                    }

                    if (!DeviceManager.Init())
                    {
                        result.success = false;
                        result.message = "DeviceManager Init Failed";
                        return result;
                    }

                    Running = true;
                    Closing = false;
                }
                else
                {
                    Logger.Error("用户名或密码错误");
                }
            }
            else
            {
                result = new HResult() { success = false, message = "未找到配置信息" };
            }

            return result;
        }

        /// <summary>
        /// 启动刻录监听
        /// </summary>
        public void OpenBurnClient()
        {
            try
            {
                MessageManager.Start();

                Logger.Info("PSDBurn已启动");
            }
            catch (Exception ex)
            { }
        }

        /// <summary>
        /// 停止刻录监听
        /// </summary>
        public void CloseBurnClient()
        {
            try
            {
                MessageManager.Stop();

                Logger.Info("PSDBurn已停止");
            }
            catch (Exception ex)
            { }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="exit"></param>
        public void Dispose(bool exit = true)
        {
            Running = false;

            Thread.Sleep(2000);

            if (exit)
            {
                Logger.Close();
            }
        }

        /// <summary>
        /// 得到一个光驱设备后触发的事件
        /// </summary>
        /// <param name="device"></param>
        private void DeviceManager_OnGetRecordingDevice(RecorderDevice device)
        {
            var status = new RecorderStatus();
            status.RecorderName = device.Name;
            status.State = (int)RecorderState.Standby;
            status.Info = "";
            BurnRuntime.RecorderStatus.Add(status);

            Logger.Log("加载光驱设备：" + device.Name);
        }

        /// <summary>
        /// 检测一个光驱内光盘信息后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="info"></param>
        private void DeviceManager_OnDetectRecorder(RecorderDevice device, string info)
        {
            var status = BurnRuntime.RecorderStatus.Where(t => t.RecorderName == device.Name).FirstOrDefault();
            if (status != null)
            {
                status.Info = info;
            }

            Logger.Log("检测媒体信息：" + device.VolumePathName + " - " + info);
        }

        /// <summary>
        /// 检测光盘是否有足够容量刻录文件后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="totalDiscSize"></param>
        /// <param name="totalMediaSize"></param>
        private void DeviceManager_OnUpdateCapacity(RecorderDevice device, long totalDiscSize, long totalMediaSize)
        {
            string info = "媒体可用大小=" + PSDFunction.FormatByteSize(totalDiscSize) + "，待刻录内容大小=" + PSDFunction.FormatByteSize(totalMediaSize);
            
            var status = BurnRuntime.RecorderStatus.Where(t => t.RecorderName == device.Name).FirstOrDefault();
            if (status != null)
            {
                status.Info = info;
            }

            Logger.Log("检测媒体信息：" + device.VolumePathName + " - " + info);
        }

        /// <summary>
        /// 光盘刻录成功后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="dvd"></param>
        /// <param name="info"></param>
        private void DeviceManager_OnBurnSuccess(RecorderDevice device, dl_burn_dvd dvd, string info)
        {
            dvd.state = 1;
            dvd.burn_end_time = DateTime.Now;

            var ret = HttpHelper.Post<HResult>(AppSettings.Setting.API.BurnDVDComplete, JsonConvert.SerializeObject(dvd));

            BurnManager.EndBurnDVD(dvd);

            Logger.Log("刻录完成：" + device.VolumePathName + " " + dvd.dvd_title + "-" + dvd.dvd_num);
        }

        /// <summary>
        /// 光盘刻录失败后触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="dvd"></param>
        /// <param name="info"></param>
        private void DeviceManager_OnBurnError(RecorderDevice device, dl_burn_dvd dvd, string info)
        {
            dvd.state = 2;
            dvd.burn_end_time = DateTime.Now;
            dvd.error_log = info;

            var ret = HttpHelper.Post<HResult>(AppSettings.Setting.API.BurnDVDComplete, JsonConvert.SerializeObject(dvd));

            BurnManager.EndBurnDVD(dvd);

            Logger.Log("刻录失败：" + device.VolumePathName + " " + dvd.dvd_title + "-" + dvd.dvd_num + " " + info);
        }

        /// <summary>
        /// 更新光盘刻录进度时触发的事件
        /// </summary>
        /// <param name="device"></param>
        /// <param name="dvd"></param>
        /// <param name="info"></param>
        /// <param name="percent"></param>
        private void DeviceManager_OnBurnProgress(RecorderDevice device, dl_burn_dvd dvd, string info, int percent)
        {
            dvd.burn_percent = percent;

            Logger.Log("正在刻录：" + device.VolumePathName + " " + dvd.dvd_title + "-" + dvd.dvd_num + " " + info);
        }

        /// <summary>
        /// 执行接收到的刻录任务
        /// </summary>
        /// <param name="msg"></param>
        public void StartBurn(BurnTask task)
        {
            BurnManager.AddTask(task);
        }

        /// <summary>
        /// 添加一个待刻录文件
        /// </summary>
        /// <param name="burnId"></param>
        /// <param name="file"></param>
        public void AddBurnFile(string burnId, dl_files file)
        {
            BurnManager.AddBurnFile(burnId, file);
        }

        /// <summary>
        /// 返回刻录进度消息
        /// </summary>
        /// <param name="remoteEP"></param>
        public void ResponseBurningDVD(IPEndPoint remoteEP)
        {
            var msg = new ResponseBurningDVDMessage();
            msg.BurnRuntime = BurnRuntime;

            MessageManager.Send(remoteEP, msg);
        }
    }

    public enum BurnType : int
    {
        单光驱刻录 = 1,
        双光驱刻录 = 2,
    }

    public enum BurnCopy : int
    {
        一式一份 = 1,
        一式两份 = 2,
    }
}
